﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using CloudShot.Forms;
using CloudShot.Properties;
using CloudShot.Utils;

namespace CloudShot
{
  internal static class Program
  {
    private static readonly Mutex Mutex = new Mutex(true, "CloudShot by name1ess0ne");

    [DllImport("shcore.dll")]
    private static extern int SetProcessDpiAwareness(ProcessDPIAwareness value);

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    private static void Main()
    {
      string errorFile = AppHelper.ErrorFile;

      Debug.WriteLine("## Error file created: " + errorFile);
      Trace.AutoFlush = true;
      Trace.Listeners.Add(new TextWriterTraceListener(errorFile));

      // Add the event handler for handling UI thread exceptions to the event.
      Application.ThreadException += UIThreadException;

      // Set the unhandled exception mode to force all Windows Forms errors to go through
      // our handler.
      Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

      // Add the event handler for handling non-UI thread exceptions to the event. 
      AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

      SetDpiAwareness();

      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);

      if (Mutex.WaitOne(TimeSpan.Zero, true))
      {
        Application.Run(new MainForm());
        Mutex.ReleaseMutex();
      }
      else
      {
        MessageBox.Show(Resources.Program_OnlyOneInstanceCanBeRun, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
      }
    }

    private static void SetDpiAwareness()
    {
      try
      {
        Version version = Environment.OSVersion.Version;
        if ((version.Major == 6 && version.Minor >= 2) || version.Major > 6)//win 8 or newer
        {
          SetProcessDpiAwareness(ProcessDPIAwareness.ProcessPerMonitorDPIAware);
        }
      }
      catch (Exception)//this exception occures if OS does not implement this API, just ignore it.
      {
      }
    }

    private static void UIThreadException(object sender, ThreadExceptionEventArgs e)
    {
      ShowThreadExceptionDialog(Application.ProductName, e.Exception);
      Application.Exit();
    }

    private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
      Exception ex = (Exception)e.ExceptionObject;
      ShowThreadExceptionDialog(Application.ProductName, ex);
      Application.Exit();
    }

    // Creates the error message and displays it.
    private static void ShowThreadExceptionDialog(string title, Exception err)
    {
      ErrorsHelper.TraceError(err);

      string errorMsg = Resources.Program_ErrorOccured + Environment.NewLine + err.Message;

#if DEBUG
      errorMsg += string.Format("{0}{0}Stack Trace:{0}{1}", Environment.NewLine, err.StackTrace);
#endif

      MessageBox.Show(errorMsg, title, MessageBoxButtons.OK, MessageBoxIcon.Stop);
    }

    #region Nested type: ProcessDPIAwareness

    private enum ProcessDPIAwareness
    {
      ProcessDPIUnaware = 0,
      ProcessSystemDPIAware = 1,
      ProcessPerMonitorDPIAware = 2
    }

    #endregion
  }
}